﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Monopoly.Domain
{
    public class Field : BoxProperty
    {
        private ConsoleColor Color;
        private IList<int> Rent;
        private IList<RealEstate> RealEstate;
        private int HousePrice;
        private int HotelPrice;

        public Field(string Name, ConsoleColor Color, int Price)
            : base(Name, Price)
        {
            this.Color = Color;
            this.RealEstate = new List<RealEstate>();

            this.Rent = new List<int>();
            this.Rent.Add(Price / 6); //Simple rent
            this.Rent.Add((int)Math.Round(Price / 1.5)); //1 house
            this.Rent.Add((int)Math.Round(Price * 1.5)); //2 houses
            this.Rent.Add(Price * 2); //3 houses
            this.Rent.Add(Price * 3); //4 houses
            this.Rent.Add(Price * 5); //1 hotel

            this.HousePrice = (int)Math.Floor(Price * 1.2);
            this.HotelPrice = this.HousePrice * 5;
        }

        /// <summary>
        /// Gets the color of the field
        /// </summary>
        /// <returns>Field's color</returns>
        public ConsoleColor GetColor()
        {
            return this.Color;
        }

        /// <summary>
        /// Return the requested rent amount depending on field's real estate.
        /// </summary>
        /// <param name="HasAllColors">Has the player all street fields</param>
        /// <returns>Requested amount for rent</returns>
        public int GetRent(bool HasAllColors = false)
        {
            if (this.RealEstate.Count() > 0)
            {
                if (this.RealEstate.Count() == 1 && this.RealEstate.First() is Hotel)
                    return this.Rent.Last();
                return this.Rent[this.RealEstate.Count()];
            }
            else if (HasAllColors)
                return this.Rent.First() * 2;
            else
                return this.Rent.First();
        }

        public IList<RealEstate> RemoveRealEstates()
        {
            IList<RealEstate> RealEstates = this.RealEstate;
            this.RealEstate = new List<RealEstate>();
            return RealEstates;
        }

        /// <summary>
        /// Check if the field has some real estate of the given type
        /// </summary>
        /// <param name="Type">Type of searched real estate</param>
        /// <returns><code>true</code> if the field contains real estate of the given type</returns>
        public bool HasRealEstate(Type Type)
        {
            return this.RealEstate.Where(re => re.GetType() == Type).Count() > 0;
        }

        /// <summary>
        /// Removes a real estate building type on the field of the given type
        /// </summary>
        /// <param name="Type">Type of the wanted real estate</param>
        public void SaleRealEstate(Bank Bank, Type Type)
        {
            RealEstate RealEstate = this.RealEstate.First();
            this.RealEstate.Remove(RealEstate);
            Bank.RedeemRealEstate(RealEstate, (Player)this.GetOwner(), (typeof(House) == Type ? this.HousePrice : this.HotelPrice));
        }

        public int GetHouseCount()
        {
            if (this.HasRealEstate(typeof(House)))
                return this.RealEstate.Count;
            else
                if (this.HasRealEstate(typeof(Hotel)))
                    return 5;
                else
                    return 0;
        }

        public int GetHousePrice()
        {
            return HousePrice;
        }

        public void AddHouse(House House)
        {
            this.RealEstate.Add(House);
        }

        public void AddHotel(Hotel Hotel)
        {
            this.RealEstate.Add(Hotel);
        }

        /// <summary>
        /// Sells all field real estate
        /// </summary>
        /// <param name="Bank">Allow bank real estate return</param>
        public void SaleAllRealEstate(Bank Bank)
        {
            foreach (RealEstate r in this.RealEstate)
                Bank.RedeemRealEstate(r, (Player)this.GetOwner(), r is House ? this.HousePrice : this.HotelPrice);
        }
    }
}
